import {
  Injectable,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like } from 'typeorm';
import { Todo } from './entities/todo.entity';
import { CreateTodoDto } from './dto/create-todo.dto';
import { UpdateTodoDto } from './dto/update-todo.dto';
import { TodoReplyService } from './todo-reply.service';
import { UploadPicturesService } from '../common/upload/upload-pictures.service';
import { TodoReply } from './entities/todo-reply.entity';
import { PaginatedResponse } from './dto/pagination.dto';

@Injectable()
export class TodoService {
  constructor(
    @InjectRepository(Todo)
    private todoRepository: Repository<Todo>,
    private todoReplyService: TodoReplyService,
    private uploadPicturesService: UploadPicturesService,
  ) {}

  async findAll(): Promise<Todo[]> {
    return this.todoRepository.find({
      where: { deleted: false },
      order: { date: 'DESC' },
    });
  }

  async findAllPaginated(
    page: number,
    limit: number,
  ): Promise<PaginatedResponse<Todo>> {
    // 确保参数在有效范围内
    const pageNum = Math.max(1, Math.min(page, 2147483647));
    const pageSize = Math.max(1, Math.min(limit, 1000)); // 限制每页最大1000条
    const skip = (pageNum - 1) * pageSize;

    const [data, total] = await this.todoRepository.findAndCount({
      where: { deleted: false },
      order: { date: 'DESC' },
      skip: skip,
      take: pageSize,
    });

    const totalPages = Math.ceil(total / pageSize);

    return {
      data,
      pagination: {
        page: pageNum,
        limit: pageSize,
        total,
        totalPages,
        hasNext: pageNum < totalPages,
        hasPrev: pageNum > 1,
      },
    };
  }

  // 验证ID是否在安全范围内
  private validateId(id: number): void {
    if (id <= 0 || id > Number.MAX_SAFE_INTEGER) {
      throw new BadRequestException(
        `Invalid ID: ${id}. ID must be between 1 and ${Number.MAX_SAFE_INTEGER}`,
      );
    }
  }

  async findById(id: number): Promise<Todo> {
    this.validateId(id);
    const todo = await this.todoRepository.findOne({
      where: { _Identify: id, deleted: false },
    });
    if (!todo) {
      throw new NotFoundException(`Todo with ID ${id} not found`);
    }
    return todo;
  }

  async findByTodoid(todoid: string): Promise<Todo> {
    const todo = await this.todoRepository.findOne({
      where: { todoid, deleted: false },
    });
    if (!todo) {
      throw new NotFoundException(`Todo with todoid ${todoid} not found`);
    }
    return todo;
  }

  async create(createTodoDto: CreateTodoDto): Promise<Todo> {
    const todo = this.todoRepository.create({
      ...createTodoDto,
      deleted: false,
    });
    return this.todoRepository.save(todo);
  }

  async update(id: number, updateTodoDto: UpdateTodoDto): Promise<Todo> {
    this.validateId(id);
    const todo = await this.findById(id);
    Object.assign(todo, updateTodoDto);
    return this.todoRepository.save(todo);
  }

  async updateByTodoid(
    todoid: string,
    updateTodoDto: UpdateTodoDto,
  ): Promise<Todo> {
    const todo = await this.findByTodoid(todoid);
    Object.assign(todo, updateTodoDto);
    return this.todoRepository.save(todo);
  }

  async delete(id: number): Promise<void> {
    this.validateId(id);
    const todo = await this.findById(id);
    todo.deleted = true;
    await this.todoRepository.save(todo);
  }

  async deleteByTodoid(todoid: string): Promise<void> {
    const todo = await this.findByTodoid(todoid);
    todo.deleted = true;
    await this.todoRepository.save(todo);
  }

  async findByAuthor(author: number): Promise<Todo[]> {
    return this.todoRepository.find({
      where: { author, deleted: false },
      order: { date: 'DESC' },
    });
  }

  async findByStatus(finished: boolean): Promise<Todo[]> {
    return this.todoRepository.find({
      where: { finished, deleted: false },
      order: { date: 'DESC' },
    });
  }

  async markAsFinished(id: number): Promise<Todo> {
    this.validateId(id);
    const todo = await this.findById(id);
    todo.finished = true;
    todo.finishtime = new Date();
    return this.todoRepository.save(todo);
  }

  async markAsFinishedByTodoid(
    todoid: string,
    finished?: boolean,
    finishtime?: string,
  ): Promise<Todo> {
    const todo = await this.findByTodoid(todoid);
    todo.finished = finished !== undefined ? finished : true;
    if (finished) {
      // 如果传入了完成时间，使用传入的时间；否则使用当前时间
      if (finishtime) {
        todo.finishtime = new Date(finishtime);
      } else {
        todo.finishtime = new Date();
      }
    } else {
      todo.finishtime = null;
    }
    return this.todoRepository.save(todo);
  }

  async searchByTitleOrContent(searchTerm: string): Promise<Todo[]> {
    return this.todoRepository.find({
      where: [
        { todotitle: Like(`%${searchTerm}%`), deleted: false },
        { todocontent: Like(`%${searchTerm}%`), deleted: false },
      ],
      order: { date: 'DESC' },
    });
  }

  async findByDepartment(department: number): Promise<Todo[]> {
    return this.todoRepository.find({
      where: { department, deleted: false },
      order: { date: 'DESC' },
    });
  }

  async findByType(type: string): Promise<Todo[]> {
    return this.todoRepository.find({
      where: { type, deleted: false },
      order: { date: 'DESC' },
    });
  }

  // 新增方法：标记为延期
  async markAsPostponed(id: number): Promise<Todo> {
    this.validateId(id);
    const todo = await this.findById(id);
    todo.postponed = true;
    return this.todoRepository.save(todo);
  }

  async markAsPostponedByTodoid(
    todoid: string,
    postponed?: boolean,
  ): Promise<Todo> {
    const todo = await this.findByTodoid(todoid);
    todo.postponed = postponed !== undefined ? postponed : true;
    return this.todoRepository.save(todo);
  }

  // 新增方法：标记为已完成并记录
  async markAsAccountCompleted(id: number): Promise<Todo> {
    this.validateId(id);
    const todo = await this.findById(id);
    todo.account_completed = true;
    todo.finished = true;
    todo.finishtime = new Date();
    return this.todoRepository.save(todo);
  }

  async markAsAccountCompletedByTodoid(todoid: string): Promise<Todo> {
    const todo = await this.findByTodoid(todoid);
    todo.account_completed = true;
    todo.finished = true;
    todo.finishtime = new Date();
    return this.todoRepository.save(todo);
  }

  // 新增方法：获取待办列表（用于小程序）
  async getQuoteList(
    searchParams: any,
  ): Promise<{ data: Todo[]; total: number }> {
    const {
      page = 1,
      limit = 10,
      type,
      department,
      author,
      finished,
    } = searchParams;
    const pageNum = Math.max(1, Math.min(parseInt(page), 2147483647));
    const pageSize = Math.max(1, Math.min(parseInt(limit), 1000));
    const skip = (pageNum - 1) * pageSize;

    const whereCondition: any = { deleted: false };
    if (type) whereCondition.type = type;
    if (department) whereCondition.department = department;
    if (author) whereCondition.author = parseInt(author);
    if (finished !== undefined) whereCondition.finished = finished === 'true';

    const [data, total] = await this.todoRepository.findAndCount({
      where: whereCondition,
      order: { date: 'DESC' },
      skip: skip,
      take: pageSize,
    });

    return { data, total };
  }

  // 加载Todo的回复（对应Java的loadTodoReply方法）
  private async loadTodoReplies(todo: Todo): Promise<void> {
    // 直接使用Repository查询，因为findByTodoId方法已被删除
    const replies = await this.todoReplyService['todoReplyRepository'].find({
      where: { todoid: todo.todoid },
      order: { replytime: 'ASC' },
    });
    
    // 为每个回复加载图片
    for (const reply of replies) {
      if (reply.picture) {
        reply['uploadpictures'] = await this.uploadPicturesService.findByServiceId(reply.picture);
      }
    }
    
    todo['replies'] = replies;
  }

  // 加载Todo的图片（对应Java的loadTodopictures方法）
  private async loadTodoPictures(todo: Todo): Promise<void> {
    if (todo.picture) {
      const pictures = await this.uploadPicturesService.findByServiceId(
        todo.picture,
      );
      todo['uploadpictures'] = pictures;
    }
  }

  // 加载回复的图片（对应Java的loadTodoReplypictures方法）
  private async loadTodoReplyPictures(todoReply: TodoReply): Promise<void> {
    if (todoReply.picture) {
      const pictures = await this.uploadPicturesService.findByServiceId(
        todoReply.picture,
      );
      todoReply['uploadpictures'] = pictures;
    }
  }

  // 获取Todo详情（对应Java的getTodoDetail方法）
  async getTodoDetail(todoid: string): Promise<Todo> {
    const todo = await this.todoRepository.findOne({
      where: { todoid, deleted: false },
    });

    if (!todo) {
      throw new NotFoundException(`Todo with todoid ${todoid} not found`);
    }

    // 加载回复
    await this.loadTodoReplies(todo);
    // 加载Todo的图片
    await this.loadTodoPictures(todo);

    return todo;
  }

  // 获取Todo详情带回复和图片（对应Java的完整逻辑）
  async getTodoDetailWithRepliesAndPictures(todoid: string): Promise<any> {
    const todo = await this.getTodoDetail(todoid);

    // 确保回复也加载了图片
    if (todo['replies'] && todo['replies'].length > 0) {
      for (const reply of todo['replies']) {
        await this.loadTodoReplyPictures(reply);
      }
    }

    return {
      success: true,
      data: todo,
      message: '获取成功',
    };
  }

  // 解析picture字段中的图片ID
  private parsePictureIds(pictureField: string): string[] {
    if (!pictureField) return [];

    // 如果是JSON格式
    try {
      const parsed = JSON.parse(pictureField);
      if (Array.isArray(parsed)) {
        return parsed;
      } else if (typeof parsed === 'string') {
        return [parsed];
      }
    } catch (e) {
      // 不是JSON格式，继续处理
    }

    // 如果是逗号分隔的字符串
    if (pictureField.includes(',')) {
      return pictureField
        .split(',')
        .map((id) => id.trim())
        .filter((id) => id);
    }

    // 单个图片ID
    return [pictureField];
  }

  // 新增方法：标记为完成（用于小程序）
  async markAsCompleteByTodoid(todoid: string): Promise<Todo> {
    return this.markAsFinishedByTodoid(todoid);
  }

  // 新增方法：延期（用于小程序）
  async extendDeadlineByTodoid(
    todoid: string,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    newDeadline: string,
  ): Promise<Todo> {
    const todo = await this.findByTodoid(todoid);
    // 由于Todo实体没有deadline字段，这里可以更新其他相关字段
    // 比如更新updatetime或者添加备注信息
    todo.updatetime = new Date();
    return this.todoRepository.save(todo);
  }

  // 新增方法：获取已完成数量
  async getCompletedCount(): Promise<number> {
    return this.todoRepository.count({
      where: { finished: true, deleted: false },
    });
  }

  // 按状态查询分页
  async findByStatusPaginated(
    finished: boolean,
    page: number,
    limit: number,
  ): Promise<PaginatedResponse<Todo>> {
    const pageNum = Math.max(1, Math.min(page, 2147483647));
    const pageSize = Math.max(1, Math.min(limit, 1000));
    const skip = (pageNum - 1) * pageSize;

    const [data, total] = await this.todoRepository.findAndCount({
      where: { finished, deleted: false },
      order: { date: 'DESC' },
      skip: skip,
      take: pageSize,
    });

    const totalPages = Math.ceil(total / pageSize);

    return {
      data,
      pagination: {
        page: pageNum,
        limit: pageSize,
        total,
        totalPages,
        hasNext: pageNum < totalPages,
        hasPrev: pageNum > 1,
      },
    };
  }

  // 按类型查询分页
  async findByTypePaginated(
    type: string,
    page: number,
    limit: number,
  ): Promise<PaginatedResponse<Todo>> {
    const pageNum = Math.max(1, Math.min(page, 2147483647));
    const pageSize = Math.max(1, Math.min(limit, 1000));
    const skip = (pageNum - 1) * pageSize;

    const [data, total] = await this.todoRepository.findAndCount({
      where: { type, deleted: false },
      order: { date: 'DESC' },
      skip: skip,
      take: pageSize,
    });

    const totalPages = Math.ceil(total / pageSize);

    return {
      data,
      pagination: {
        page: pageNum,
        limit: pageSize,
        total,
        totalPages,
        hasNext: pageNum < totalPages,
        hasPrev: pageNum > 1,
      },
    };
  }

  // 搜索分页
  async searchByTitleOrContentPaginated(
    searchTerm: string,
    page: number,
    limit: number,
  ): Promise<PaginatedResponse<Todo>> {
    const pageNum = Math.max(1, Math.min(page, 2147483647));
    const pageSize = Math.max(1, Math.min(limit, 1000));
    const skip = (pageNum - 1) * pageSize;

    const [data, total] = await this.todoRepository.findAndCount({
      where: [
        { todotitle: Like(`%${searchTerm}%`), deleted: false },
        { todocontent: Like(`%${searchTerm}%`), deleted: false },
      ],
      order: { date: 'DESC' },
      skip: skip,
      take: pageSize,
    });

    const totalPages = Math.ceil(total / pageSize);

    return {
      data,
      pagination: {
        page: pageNum,
        limit: pageSize,
        total,
        totalPages,
        hasNext: pageNum < totalPages,
        hasPrev: pageNum > 1,
      },
    };
  }




}